package com.ruoyi.bearing.service.Impl;

import com.alibaba.fastjson2.JSONObject;
import com.ruoyi.bearing.domain.*;
import com.ruoyi.bearing.mapper.ModelInfoMangmentMapper;
import com.ruoyi.bearing.mapper.ModelTestMapper;
import com.ruoyi.bearing.mapper.ModelTestResultMapper;
import com.ruoyi.bearing.mapper.ModelTrainMapper;
import com.ruoyi.bearing.service.IModelInfoMangmentService;
import com.ruoyi.bearing.service.IModelTestService;
import com.ruoyi.common.constant.DiagnosisRules;
import com.ruoyi.common.constant.FlaskModelConstants;
import com.ruoyi.common.enums.DiagnosisModelType;
import com.ruoyi.common.enums.QueryState;
import com.ruoyi.common.enums.TrainState;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.file.FileUploadUtils;
import com.ruoyi.common.utils.flask.HttpFlask;
import com.ruoyi.common.utils.uuid.IdUtils;
import io.swagger.annotations.ApiModel;
import org.skyscreamer.jsonassert.comparator.JSONCompareUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * 模型测试
 */
@Service
public class ModelTestServiceImpl implements IModelTestService {
    @Autowired
    ModelTestResultMapper modelTestResultMapper;
    @Autowired
    ModelTestMapper modelTestMapper;
    @Autowired
    ModelInfoMangmentMapper modelInfoMangmentMapper;

    /**
     * 模型测试
     */
    @Override
    public String startModelTest(MultipartFile file, ModelTest modelTest) throws IOException, IllegalAccessException {
        String res = HttpFlask.sendGetFlask(FlaskModelConstants.Model_TEST_FILE_URL);
        String result = QueryState.SUCCESS.getInfo();
        if (!"".equals(res)) {
            JSONObject jsonObject = JSONObject.parseObject(res);
            String dir = (String) jsonObject.get("data");
            String csvName = FileUploadUtils.upload(dir, file);
            modelTest.setFileName(csvName.split("test/")[1]);
            String postParam = HttpFlask.getKeyAndValueString(modelTest);
            String resPost = HttpFlask.sendPostFlask(FlaskModelConstants.Model_TEST_URL, postParam);
            int response = getModelTestResult(modelTest, resPost);
            if (1 == response) {
                result = QueryState.FAIL.getInfo();
            }
            if (2 == response) {
                result = QueryState.errorFile.getInfo();
            }
        } else {
            result = QueryState.FAIL.getInfo();
            return result;
        }
        return result;
    }

    public List<ModelTestResult> selectModelTestResult(String mid) {
        ModelTestResult modelTestResult = new ModelTestResult();
        modelTestResult.setMid(mid);
        return modelTestResultMapper.selectModelTestResult(modelTestResult);
    }

    public List<ModelTest> selectModelTest(ModelTest modelTest) {
        List<ModelTest> list = modelTestMapper.selectModelTestList(modelTest);
        for (ModelTest model : list) {
            String a = model.getResult();
            if (model.getResult().equals("0")) {
                model.setResult("正常");
            } else {
                model.setResult("一般");
            }
        }
        return list;
    }

    public int deleteModelTestByMids(String[] mids) {
        return modelTestResultMapper.deleteModelTestResultByMids(mids) + modelTestMapper.deleteModelTestByMids(mids);
    }

    private int getModelTestResult(ModelTest modelTest, String res) {
        JSONObject jsonObject = JSONObject.parseObject(res);
        JSONObject testRes = (JSONObject) jsonObject.get("data");
        int result = 0;
        if (testRes != null) {
            if (testRes.containsKey("errorFile")) {
                result = 2;
                return result;
            }
            ModelTestResult modelTestResult = new ModelTestResult();
            modelTestResult.setMid(modelTest.getMid());
            Date date = DateUtils.getNowDate();
            modelTestResult.setCreateTime(date);
            modelTest.setCreateTime(date);
            int s = 0;
            try {
                modelTestResultMapper.deleteModelTestResult(modelTestResult);
                modelTestMapper.deleteModelTestByMid(modelTest);
                for (String key : testRes.keySet()) {
                    modelTestResult.setId(IdUtils.simpleUUID());
                    modelTestResult.setMetrics(key);
                    modelTestResult.setValue((String) testRes.get(key));
                    s += testRules(modelTestResult);
                    modelTestResultMapper.insertModelTestResult(modelTestResult);
                }
                if (4 == s) {
                    modelTest.setResult("0");
                } else {
                    modelTest.setResult("1");
                }
                modelTest.setName(modelInfoMangmentMapper.selectModelInfoMangmentByMid(modelTest.getMid()).getName());
                modelTestMapper.insertModelTest(modelTest);
            } catch (Exception e) {
                result = 1;
                e.printStackTrace();
            }
        }
        return result;
    }

    private int testRules(ModelTestResult modelTestResult) {
        String mid = modelTestResult.getMid();
        String type = mid.substring(0, 4);
        if (type.equals("diag")) {
            return diagnosisRules(modelTestResult);
        } else {
            return rulRules(modelTestResult);
        }
    }

    private int diagnosisRules(ModelTestResult modelTestResult) {
        String type = modelTestResult.getMetrics();
        double value = Double.parseDouble(modelTestResult.getValue());
        int s = 0;
        if (type.equals("Accuracy")) {
            modelTestResult.setResult(value < DiagnosisRules.ACCURACY_RULES ? "1" : "0");
            if (modelTestResult.getResult().equals("0")) {
                s += 1;
            }
        }
        if (type.equals("Precision")) {
            modelTestResult.setResult(value < DiagnosisRules.PRECISION_RULES ? "1" : "0");
            if (modelTestResult.getResult().equals("0")) {
                s += 1;
            }
        }
        if (type.equals("Recall")) {
            modelTestResult.setResult(value < DiagnosisRules.RECALL_RULES ? "1" : "0");
            if (modelTestResult.getResult().equals("0")) {
                s += 1;
            }
        }
        if (type.equals("F1")) {
            modelTestResult.setResult(value < DiagnosisRules.F1SCORE_RULES ? "1" : "0");
            if (modelTestResult.getResult().equals("0")) {
                s += 1;
            }
        }
        return s;
    }

    private int rulRules(ModelTestResult modelTestResult) {
        return 0;
    }
}
